<template>
  <div>
    <label :for="labelFor" v-if="label" :class="{'label-required': isRequired}" :style="style">{{label}}</label>
    <slot></slot>
    <div v-if="isShowMes" class="message">{{message}}</div>
  </div>
</template>
<script>
import AsyncValidator from 'async-validator';
// import Emitter from '@/mixins/emitter.js';
export default {
  name: 'IFormItem',
  // mixins: [ Emitter ],
  inject: [ 'form' ], /**一个字符串数组，或
   一个对象，对象的 key 是本地的绑定名，value 是：
   在可用的注入内容中搜索用的 key (字符串或 Symbol)，或
   一个对象，该对象的：
   from 属性是在可用的注入内容中搜索用的 key (字符串或 Symbol)
   default 属性是降级情况下使用的 value*/
  props: {
    label: { type: String, default: '' }, //获取label
    prop: { type: String }, //接收每个item的prop

    pFormItemStyle: {
      type: Object,
      default () {
        return {}
      }
    }
  },
  data() {
    return {
      isRequired: false, //决定展示是否必填
      isShowMes: false, //决定展示是否显示
      message: '', //消息提示
      labelFor: 'input' + new Date().valueOf(),

      style: this.pFormItemStyle
    }
  },
  mounted() {
    if (this.prop) { //如果prop存在
      // console.log('formItem的mounted:' + this.prop);
      this.dispatch('IForm', 'form-add', this); //等于dispatch,把本组件加入到form中
      // 设置初始值
      this.initialValue = this.fieldValue;
      this.setRules(); //调用把该组件的rules规则传入form的方法
    }
  },
  // 组件销毁前，将实例从 Form 的缓存中移除
  beforeDestroy () {
    this.dispatch('IForm', 'form-remove', this);
  },
  computed: {

    /**返回prop至form组件的model*/
    fieldValue() {
      return this.form.model[this.prop]
    }
  },
  methods: {

    /**赋予rules规则*/
    setRules() {
      let rules = this.getRules(); //先获取所有的rules
      if (rules.length) {
        rules.forEach(rule => {
          if (rule.required !== undefined) this.isRequired = rule.required //如果发现required即必填 定义,就让其等于isRequired,使这个组件能够显示必填标识
        });
      }
      this.$on('form-blur', this.onFieldBlur); // 接收子组件的dispatch发来的方法form-blur,失去焦点
      this.$on('form-change', this.onFieldChange); // 接收子组件的dispatch发来的方法form-change,改变
    },

    /**获取约束规则*/
    getRules() {
      let formRules = this.form.rules;
      formRules = formRules ? formRules[this.prop] : [];
      return formRules;
    },

    /**过滤出符合要求的 rule 规则*/
    getFilteredRule (trigger) {
      const rules = this.getRules();
      return rules.filter(rule => !rule.trigger || rule.trigger.indexOf(trigger) !== -1);
    },

    /**对父组件的操作*/
    dispatch(componentName, eventName, params) {
      // console.log('formItem的dispatch方法');
      let parent = this.$parent || this.$root; // 这里用来获取父组件或根组件<父组件不存在>对象
      // console.log('dispatch方法的parent' + typeof parent);
      // console.log(parent);
      let name = parent.$options.name; // 这里用来获取父组件的名字即<iFrom>;this.$options 即可以获取自定义属性，也可以增加自定义属性;并且有两种获取自定义属性的方法 $options.['name'] $options.name
      // console.log('dispatch方法的name=' + name);
      while (parent && (!name || name !== componentName)) { /**当父组件名<IForm>不存在或者不相等 且父组件对象存在时*/

        parent = parent.$parent; //
        if (parent) name = parent.$options.name; //如果父组件存在,就让name等于父组件的名字
      }

      if (parent) parent.$emit.apply(parent, [eventName].concat(params));
    },

    /**对子组件的操作*/
    broadcast(componentName, eventName, params) {
      this.$children.forEach(child => {
        const name = child.$options.name;
        if (name === componentName) child.$emit.apply(child, [eventName].concat(params));
        else broadcast.apply(child, [componentName, eventName].concat([params]));
      });
    },

    /**
     * 校验表单数据,本质是对async-validator的封装,使其能够更好的使用
     * @param trigger 触发校验类型
     * @param callback 回调函数
     */
    validate(trigger, cb) {
      let rules = this.getFilteredRule(trigger); // 获取全部的规则
      if(!rules || rules.length === 0) return true; //如果没有rules数组或者rules数组的长度长度为0,即没有验证规则,返回true,验证结束

      // 使用 async-validator
      const validator = new AsyncValidator({
          [this.prop]: rules
        });


      let model = {[this.prop]: this.fieldValue};
      // console.log('validate方法的model:' + model);
      // console.log(model);
      validator.validate(model, { firstFields: true }, errors => {
        this.isShowMes = errors ? true : false;
        this.message = errors ? errors[0].message : '';
        if (cb) cb(this.message);
      })
    },

    /**重置该组件*/
    resetField () {
      this.message = '';
      this.form.model[this.prop] = this.initialValue;
    },

    /**该组件失焦时*/
    onFieldBlur() {
      this.validate('blur'); //调用校验函数,trigger为blur
    },

    /**该组件改变时*/
    onFieldChange() {
      this.validate('change'); //调用校验函数,trigger为change
    }
  }
}
</script>
<style scoped>
  label {
    font-size: 25px;
  }
  .label-required:before { /*必填的label*/
    /*content: '*';*/
    color: red;
  }
  .message { /*消息提示*/

    font-size: 12px;
    color: red;
  }
</style>